package com.coderxq.blog.web.service.menu.impl;

import cn.hutool.core.util.IdUtil;
import com.coderxq.blog.exception.WsException;
import com.coderxq.blog.web.dao.MenuMapper;
import com.coderxq.blog.web.dao.RoleMapper;
import com.coderxq.blog.web.entity.pojo.Menu;
import com.coderxq.blog.web.entity.vo.MenuInfo;
import com.coderxq.blog.web.service.menu.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: lijingming
 * @Date: 2025/2/13
 * @Description:
 **/
@Component
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    RoleMapper roleMapper;

    @Override
    public Integer addMenu(Menu menu) {
        if (menu == null)  return null;
        String snowflakeId = IdUtil.getSnowflakeNextIdStr();
        menu.setMenuId(snowflakeId);
        return menuMapper.insertMenu(menu);
    }

    @Override
    public ArrayList<MenuInfo> findAllMenu() {
       try{
           ArrayList<Menu> orgMenu= menuMapper.findAllMenu();
           //将菜单格式化成树形结构
           return formatMenu(orgMenu);
       }catch (Exception e){
           throw  new WsException(e.getMessage());
       }
    }


    //格式化菜单项 将一维菜单数组转化为树形结构
    public ArrayList<MenuInfo>  formatMenu(ArrayList<Menu> orgMenu) {
        ArrayList<MenuInfo> menuInfos=new ArrayList<>();
        ArrayList<Menu> childrenMenu=new ArrayList<>();
        for(Menu menu:orgMenu){
            if(menu.getParentId()==null||menu.getParentId().isEmpty()||menu.getParentId()==""){
                MenuInfo menuInfo=new MenuInfo();
                menuInfo.setMenuId(menu.getMenuId());
                menuInfo.setMenuName(menu.getMenuName());
                menuInfo.setRoutePath(menu.getRoutePath());
                menuInfo.setType(menu.getType());
                menuInfo.setLevel(menu.getLevel());
                menuInfo.setIcon(menu.getIcon());
                menuInfo.setParentId(menu.getParentId());
                menuInfo.setIsForbidden(menu.getIsForbidden());
                menuInfos.add(menuInfo);
            }else{
                childrenMenu.add(menu);
            }
        }

        for (MenuInfo menuInfo:menuInfos){
            childrenMenu =  formatChildMenu(menuInfo,childrenMenu);
        }
        return menuInfos;
    }


    //递归将子菜单正确的插入到父菜单中
    public ArrayList<Menu>  formatChildMenu(MenuInfo fatherMenu ,ArrayList<Menu> orgMenu) {
        ArrayList<Menu> childrenMenu=new ArrayList<>();
        ArrayList<MenuInfo> menuInfos=new ArrayList<>();

        for(Menu menu:orgMenu){
            if(menu.getParentId().equals(fatherMenu.getMenuId())){
                MenuInfo menuInfo=new MenuInfo();
                menuInfo.setMenuId(menu.getMenuId());
                menuInfo.setMenuName(menu.getMenuName());
                menuInfo.setRoutePath(menu.getRoutePath());
                menuInfo.setType(menu.getType());
                menuInfo.setLevel(menu.getLevel());
                menuInfo.setIcon(menu.getIcon());
                menuInfo.setParentId(menu.getParentId());
                menuInfo.setIsForbidden(menu.getIsForbidden());
                fatherMenu.getChildren().add(menuInfo);
                menuInfos.add(menuInfo);
            }else{
                childrenMenu.add(menu);
            }
        }
        for (MenuInfo menuInfo:menuInfos){
            childrenMenu =  formatChildMenu(menuInfo,childrenMenu);
        }

        return childrenMenu;
    }

    @Override
    public Integer updateMenu(Menu menu) {
        if (menu == null)  return null;
        return menuMapper.updateMenu(menu);
    }

    @Override
    public Integer deleteMenu(String menuId) {
        if (menuId == null)  return null;
        return menuMapper.deleteMenu(menuId);
    }

    @Override
    public void saveMenusTreeData(ArrayList<MenuInfo> MenusTreeData) {
            //先将树形菜单结构拍平
            Map<String,Menu> saveMenusMap=new HashMap<>();
            flattenMenusTreeData(MenusTreeData,saveMenusMap);
            //获取数据库中的初始原菜单数据 和需要保存的数据进行比较 。
            ArrayList<Menu> orgMenusList=menuMapper.findAllMenu();
            Map<String,Menu> orgMenusMap=new HashMap<>();
            for(Menu menu:orgMenusList){
                orgMenusMap.put(menu.getMenuId(),menu);
            }
           // 若保存的数据出现新的数据则进行新增，若数据库中存在则进行更新。若发现与原数据进行对比有数据不存在了则进行删除
            ArrayList<Menu> needInsertMenuList=new ArrayList<>();
            ArrayList<Menu> needUpdateMenuList=new ArrayList<>();
            ArrayList<Menu> needDeleteMenuList=new ArrayList<>();


            for(Menu menu:saveMenusMap.values()){
                if(orgMenusMap.containsKey(menu.getMenuId())){
                    needUpdateMenuList.add(menu);
                }else{
                    needInsertMenuList.add(menu);
                }
            }


            for (Menu menu:orgMenusList){
                if(!saveMenusMap.containsKey(menu.getMenuId())){
                    needDeleteMenuList.add(menu);

                }
            }

            if(needDeleteMenuList.size()>0){
                menuMapper.deleteMenus(needDeleteMenuList); //删除菜单表中的数据
                roleMapper.deleteMenus(needDeleteMenuList);
            }
            if(needInsertMenuList.size()>0){
                menuMapper.insertMenus(needInsertMenuList);
            }
            if(needUpdateMenuList.size()>0){
                menuMapper.updateMenus(needUpdateMenuList);
            }


        }


   //将树形结构的菜单数据拍平
    public void flattenMenusTreeData(ArrayList<MenuInfo> MenusTreeData, Map<String,Menu> saveMenusMap) {
        for (MenuInfo menuInfo : MenusTreeData) {
            Menu menu = new Menu();
            menu.setMenuId(menuInfo.getMenuId());
            menu.setMenuName(menuInfo.getMenuName());
            menu.setRoutePath(menuInfo.getRoutePath());
            menu.setType(menuInfo.getType());
            menu.setLevel(menuInfo.getLevel());
            menu.setIcon(menuInfo.getIcon());
            menu.setParentId(menuInfo.getParentId());
            menu.setIsForbidden(menuInfo.getIsForbidden());
            saveMenusMap.put(menu.getMenuId(), menu);
            if (menuInfo.getChildren().size() > 0) {
                flattenMenusTreeData(menuInfo.getChildren(), saveMenusMap);
            }
        }
    }
}
